package androidx.documentfile.provider

import android.content.Context
import android.database.Cursor
import android.provider.DocumentsContract
import android.text.TextUtils
import timber.log.Timber

object DocumentExt {
    private fun findFileIntel(
        context: Context,
        file: TreeDocumentFile,
        name: String
    ): TreeDocumentFile? {
        val resolver = context.contentResolver
        val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
            file.uri,
            DocumentsContract.getDocumentId(file.uri)
        )
        var c: Cursor? = null
        try {
            c = resolver.query(
                childrenUri,
                arrayOf(
                    DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                    DocumentsContract.Document.COLUMN_DISPLAY_NAME
                ),
                null,
                null,
                null
            )
            while (c!!.moveToNext()) {
                val documentName = c.getString(1)
                if (TextUtils.equals(name, documentName)) {
                    val documentId = c.getString(0)
                    val documentUri =
                        DocumentsContract.buildDocumentUriUsingTree(file.uri, documentId)
                    return TreeDocumentFile(file, context, documentUri)
                }
            }
        } catch (e: Exception) {
            Timber.w("DocumentUtils", "Failed query: $e")
        } finally {
            c?.close()
        }
        return null
    }

    fun findFile(context: Context, documentFile: DocumentFile, name: String): DocumentFile? {
        return if (documentFile is TreeDocumentFile) findFileIntel(
            context,
            documentFile,
            name
        ) else documentFile.findFile(
            name
        )
    }

    private fun filterFiles(
        context: Context,
        file: TreeDocumentFile,
        filter: IFileFilter
    ): List<DocumentFile> {
        val resolver = context.contentResolver
        val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
            file.uri,
            DocumentsContract.getDocumentId(file.uri)
        )
        val filtered: MutableList<DocumentFile> = ArrayList()
        var c: Cursor? = null
        try {
            c = resolver.query(
                childrenUri,
                arrayOf(
                    DocumentsContract.Document.COLUMN_DOCUMENT_ID,
                    DocumentsContract.Document.COLUMN_DISPLAY_NAME
                ),
                null,
                null,
                null
            )
            while (c!!.moveToNext()) {
                val documentName = c.getString(1)
                val documentId = c.getString(0)
                val documentUri =
                    DocumentsContract.buildDocumentUriUsingTree(file.uri, documentId)
                val child = TreeDocumentFile(file, context, documentUri)
                if (child.isDirectory) filtered.addAll(
                    filterFiles(
                        context,
                        child,
                        filter
                    )
                ) else if (filter.accept(documentName)) filtered.add(child)
            }
        } catch (e: Exception) {
            Timber.w("DocumentUtils", "Failed query: $e")
        } finally {
            c?.close()
        }
        return filtered
    }

    fun filterFiles(
        context: Context,
        documentFile: DocumentFile,
        filter: IFileFilter
    ): List<DocumentFile> {
        if (documentFile is TreeDocumentFile) return filterFiles(
            context,
            documentFile as TreeDocumentFile,
            filter
        )
        val filtered: MutableList<DocumentFile> = ArrayList()
        val files = documentFile.listFiles()
        for (file in files) {
            if (filter.accept(file.name)) filtered.add(file)
        }
        return filtered
    }

    interface IFileFilter {
        fun accept(name: String?): Boolean
    }
}